#include "cirQueue.hpp"
#include <unistd.h>
#include <ctime>
#include <cstdlib>
#include "Task.hpp"
#include "Thread.hpp"

static const int p_num = 10;
static const int c_num = 10;

void *productor(void *args)
{
    cirQueue<Task> *pcq = static_cast<cirQueue<Task> *>(args);

    srand(time(nullptr) ^ pthread_self());
    static std::string opts = "+-*/%";
    while (true)
    {
        // sleep(1);
        // 生产数据
        int x = rand() % 10 + 1;
        int y = rand() % 10 + 1;
        char opt = opts[(x * y) % opts.size()];

        // 向cq传入任务
        Task t(x, y, opt);
        pcq->push(t);

        std::cout << "productor: " << t.equation() << " "
                  << "?" << std::endl;
    }

    return nullptr;
}

void *consumer(void *args)
{
    cirQueue<Task> *pcq = static_cast<cirQueue<Task> *>(args);

    while (true)
    {
        // 从cq中取出数据
        Task t;
        pcq->pop(&t);

        // 处理数据
        t();
        usleep(10000);

        std::cout << "consumer: " << t.equation() << " " << t.getResult() << std::endl;
    }

    return nullptr;
}

int main()
{
    cirQueue<Task> cq;

    // 单生产——单消费
    // pthread_t p, c;
    // pthread_create(&p, nullptr, productor, &cq);
    // pthread_create(&c, nullptr, consumer, &cq);

    // pthread_join(p, nullptr);
    // pthread_join(c, nullptr);

    // 多生产——多消费
    // pthread_t p[p_num], c[c_num];

    // for (int i = 0; i < p_num; i++)
    //     pthread_create(p + i, nullptr, productor, &cq);

    // for (int i = 0; i < c_num; i++)
    //     pthread_create(c + i, nullptr, consumer, &cq);

    // for (int i = 0; i < p_num; i++)
    //     pthread_join(p[i], nullptr);

    // for (int i = 0; i < c_num; i++)
    //     pthread_join(c[i], nullptr);

    Thread p[p_num], c[c_num];
    for (int i = 0; i < p_num; i++)
    {
        p[i] = Thread(i, productor, &cq);
        p[i].run();
    }

    for (int i = 0; i < c_num; i++)
    {
        c[i] = Thread(i, consumer, &cq);
        c[i].run();
    }

    for (int i = 0; i < p_num; i++)
        p[i].join();

    for (int i = 0; i < c_num; i++)
        c[i].join();

    return 0;
}